package com.meisen.springboot.interceptor;

import com.meisen.springboot.entity.IpBlackList;
import com.meisen.springboot.exception.RequestLimitException;
import com.meisen.springboot.service.IpBlackListService;
import com.meisen.springboot.service.IpWhiteListService;
import com.meisen.springboot.util.IpAddressUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * Url拦截器
 * @author meisen
 * 2018-05-09
 */
public class URLInterceptor implements HandlerInterceptor {
    private static final Logger LOGGER = LoggerFactory.getLogger(URLInterceptor.class);

    //用于存储记录
    private static Map<String, Integer> cache = new HashMap<>();
    private final IpAddressUtils ipAddressUtils;
    private final IpBlackListService ipBlackListService;
    private final IpWhiteListService ipWhiteListService;

    public URLInterceptor(IpBlackListService ipBlackListService, IpAddressUtils ipAddressUtils, IpWhiteListService ipWhiteListService) {
        this.ipBlackListService = ipBlackListService;
        this.ipAddressUtils = ipAddressUtils;
        this.ipWhiteListService = ipWhiteListService;
    }


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        String ip = ipAddressUtils.getIpAddress(request);
        List<String> ipWhiteList = ipWhiteListService.findAllIpWhite();
        IpBlackList blackLists = ipBlackListService.findByIp(ip);
        if (blackLists == null){
            urlHandle(request, 3600, 40, ip);
        } else if (ipWhiteList.contains(ip)) {
            return true;
        } else {
            throw new RequestLimitException();
        }
        return true;
    }

    /**
     * 处理url
     * @param request 请求
     * @param limitTime 限制时间 毫秒为单位
     * @param limitCount  限制次数
     * @param ip 处理ip
     * @throws RequestLimitException 请求限制异常
     */
    private void urlHandle(HttpServletRequest request, long limitTime, int limitCount, String ip) throws RequestLimitException {
        String url = request.getRequestURL().toString();
        final String key = "req_limit_".concat(url).concat("_").concat(ip);

        LOGGER.info("ip = " + ip + "\n" + " url = " + url + "\n" + " key = " + key);

        if (cache.get(key) == null || cache.get(key) == 0) {
            cache.put(key, 1);
        } else {
            cache.put(key, cache.get(key) + 1);
        }
        int count = cache.get(key);
        if (count > 0) {
            Timer timer = new Timer();
            TimerTask task = new TimerTask() {    //创建一个新的计时器任务。
                @Override
                public void run() {
                    if (!key.equals("")) {
                        cache.remove(key);
                    }
                }
            };
            timer.schedule(task, limitTime);
            //安排在指定延迟后执行指定的任务。task : 所要安排的任务。limitTime : 执行任务前的延迟时间，单位是毫秒。
        }
        if (count > limitCount) { //符合锁定条件
            IpBlackList blackList = new IpBlackList();
            blackList.setIp(ip);
            ipBlackListService.addIpBlackList(blackList);
            throw new RequestLimitException();
        }
    }
}
